﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MMessaging.Address.Services;
using MMessaging.Address;
using MMessaging.RequestResponse.Test.Common;
using MMessaging.MessagingEx.Common;

namespace MMessaging.RequestResponse.Test.Services
{
	public class GuestService : 
		MAddressServiceBase,
		IWaitressMessagesFunctions
	{
		private WaitressMessagesPlugIn _waitressPlugIn;

		public GuestService(MAddress guestAddress): base(
				serviceAddress:guestAddress,
				intervallTimeAlifeMessage:2000, // time-intervall for alife-message
				// roles of this service
				roles:RestaurantGlobals.GuestRole)
		{
			_waitressPlugIn = new WaitressMessagesPlugIn(ServiceAddress, this);
			_waitressPlugIn.InitPlugIn(this, PostMessage);
		}
			
		void IWaitressMessagesFunctions.OnOrder(IMTask<MAddressMessageBase> task, Order msg)
		{
			// guest may not receive a message Order
			if (!msg.Sender.Equals(this.ServiceAddress))
				throw new ApplicationException("67hdheh2i3e6sdg");
		}

		void IWaitressMessagesFunctions.OnAskForBill(IMTask<MAddressMessageBase> task, AskForBill msg)
		{
			// guest may not receive a message AskForBill
			if (!msg.Sender.Equals(this.ServiceAddress))
				throw new ApplicationException("js7e6hajdgv1qz67sf");
		}

		void IWaitressMessagesFunctions.OnPay(IMTask<MAddressMessageBase> task, Pay msg)
		{
			// guest may not receive a message Pay
			if (!msg.Sender.Equals(this.ServiceAddress))
				throw new ApplicationException("hszdf5shxhahd6db1");
		}

		private void OnEntering(IMTask<MAddressMessageBase> task)
		{
			_waitressPlugIn.SayHelloToWaitress(task, RestaurantGlobals.WaitressRole, 1000);
			// read the menu, then then make an order to any waitress (may be another waitress)
			task.SleepWithException(1000);

			if (IsCanceling)
				return;

			// order all items in the menu
			var orderParts = RestaurantGlobals.Menu.Keys.ToArray().ToList();
			bool ordered = false;
			while (!ordered)
			{
				var orderResp = _waitressPlugIn.Order(
					task,
					RestaurantGlobals.WaitressRole,
					orderParts,
					10000);

				if (IsCanceling)
					return;

				//  if some of the items are not available today
				if (orderResp.NotAvailableOrders.Count > 0)
				{
					// remove it from order
					foreach (var notAvailableItem in orderResp.NotAvailableOrders)
						orderParts.Remove(notAvailableItem);
				}
				else
				{
					ordered = true;
				}
			}

			// eat
			task.SleepWithException(2000);

			if (IsCanceling)
				return;

			// ask for bill
			var billMsg = _waitressPlugIn.AskForBill(task, RestaurantGlobals.WaitressRole, 2000);

			if (IsCanceling)
				return;

			// pay the bill
			var payAnswer = _waitressPlugIn.Pay(
				task,
				billMsg.Sender,
				(int)Math.Floor(billMsg.BillAmount * 1.1),
				1000);

			// now go ....
		}

		protected override void OnMessage(IMTask<MAddressMessageBase> context)
		{
			if (context.CurrentMessage != null)
				// System.Diagnostics.Debug.WriteLine("GTZZGX guest service received " + context.CurrentMessage.ToString());
			if (context.CurrentMessage is LetGuestEnter)
				OnEntering(context);
		}

		void IWaitressMessagesFunctions.OnSayHelloToWaitress(IMTask<MAddressMessageBase> task, SayHelloToWaitress msg)
		{
			if ( !msg.Sender.Equals(this.ServiceAddress) )
				// may not receive this message !
				throw new ApplicationException("nsdjcwe67623hagvx");
		}
	}
}
